<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var o1={
            name:"你好",
            age:12,
            sayName:function(){
                console.log(this.name);
            },
            add:function(num1,num2){
                console.log(num1+num2);
            }
        }
        var o2={
            name:"久久",
            age:20
        }
        o1.sayName.call(o2);
        o1.add.call(o2,12,12);

        //伪代码:
        // o1.sayName.call(o2);
        // fn(){

        // }.call(obj,参数);
        // obj.fn(参数)
        


        //apply 和call的几乎一样  
        //区别就是apply方法的参数都放在一个数组里面,这个数组可以是一个类数组或是标准数组
        o1.sayName.apply(o2);
        o1.add.apply(o2,[12,12]);



        // bind
       // bind()方法创建一个新的函数，在调用时设置this关键字为提供的值。
        //并在调用新函数时，将绑定时给定参数列表作为原函数的参数序列的前若干项。
        var fn= o1.add.bind(o2,10);
            fn(12);
            fn(22);
            fn(22,12);
        //注意: 调用新函数时，原来在绑定时给定的参数列表将会
        //永远作为参数组的前几项输入进来
        // demo 1
        var liList=document.querySelectorAll("ul li");//NodeList
        liList.forEach(function(item,index,arr){
            console.log(item);
            console.log(index);
        })
        var liList1=document.getElementsByTagName("li");//集合
        Array.prototype.forEach.call(liList1,function(item,index,arr){
            console.log(item);
            console.log(index);
        });
        
        // demo2
        


    </script>
</body>
</html>